package tresp.bthreads;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.atomic.AtomicReference;

import robocode.ScannedRobotEvent;
import robocode.util.Utils;
import tresp.coordinator.ICoordinator;
import tresp.utils.BThreadVote;
import tresp.utils.ITankInfo;
import tresp.utils.WaveBullet;


/**
 * <b>GueesFactorTargeting</b>
 * 
 * 
 * 
 * @author <font color="blue">Maxim Kirilov</font>
 *
 */
public class GueesFactorTargeting extends BThread {

    
    private List<WaveBullet> lWaves; 
    
    private static int[][] stats = new int[13][31];
    
    private int direction = 1;
    
    private AtomicReference<ScannedRobotEvent>  lastScannedRobotEvent;
    
    private ITankInfo tankInfo;
    
    
    public GueesFactorTargeting(ICoordinator<BThreadVote> coordinator) {
	super(coordinator);
	
	lWaves = new ArrayList<WaveBullet>();
	lastScannedRobotEvent = new AtomicReference<ScannedRobotEvent>();
	tankInfo = coordinator.getTankInfo();
    }

    @Override
    public void vote() {
	
	ScannedRobotEvent enemy = lastScannedRobotEvent.getAndSet( null );
	if ( enemy != null && !tankInfo.isTeammate( enemy.getName() )){
	    
	    // Enemy absolute bearing, you can use your one if you already declare it.
	    double absBearing = tankInfo.getHeadingRadians() + enemy.getBearingRadians();

	    // find our enemy's location:
	    double ex = tankInfo.getX() + Math.sin(absBearing) * enemy.getDistance();
	    double ey = tankInfo.getY() + Math.cos(absBearing) * enemy.getDistance();
	    
	    
	    for (int i=0; i < lWaves.size(); i++){
		WaveBullet currentWave = lWaves.get(i);
		if (currentWave.checkHit(ex, ey, tankInfo.getTime()))
		{
		    lWaves.remove( currentWave );
		    i--;
		}
	    }
	    
	    double power = Math.min(500 / enemy.getDistance(), 3);

	    if (enemy.getVelocity() != 0)
	    {
		if (Math.sin(enemy.getHeadingRadians()-absBearing) * enemy.getVelocity() < 0){
		    direction = -1;   
		}else{
		    direction = 1;
		}
	    }
	    int[] currentStats = stats[(int)(enemy.getDistance() / 100)]; // This seems silly, but I'm using it to
	    // show something else later
	    WaveBullet newWave = new WaveBullet(tankInfo.getX(), tankInfo.getY(), absBearing, power,
		    direction, tankInfo.getTime(), currentStats);
	    
	    
	    int bestindex = 15;	// initialize it to be in the middle, guessfactor 0.
	    for (int i=0; i<31; i++){
		if (currentStats[bestindex] < currentStats[i]){
		    bestindex = i;
		}
	    }
	    // this should do the opposite of the math in the WaveBullet:
	    double guessfactor = (double)(bestindex - (stats.length - 1) / 2)
		    / ((stats.length - 1) / 2);
	    double angleOffset = direction * guessfactor * newWave.maxEscapeAngle();
	    double gunAdjust = Utils.normalRelativeAngle(absBearing - tankInfo.getGunHeadingRadians() + angleOffset);
	    
	    coordinator.vote(createBThreadVote(BThreadType.TURN_GUN_RIGHT_RADIANS, weight, gunAdjust));
	    
	    if ((Math.abs( tankInfo.getGunTurnRemaining() ) < 10) && (tankInfo.getGunHeat() == 0)){
		coordinator.vote(createBThreadVote(BThreadType.FIRE, weight, power));
	    }
	    
	    
	}

    }

    @Override
    public void onScannedRobot(ScannedRobotEvent e){
	lastScannedRobotEvent.set( e );
    }
    
    
    @Override
    public String getName() {
	return "GueesFactorTargeting";
    }

}
